home *** CD-ROM | disk | FTP | other *** search
/ Almathera Ten Pack 3: CDPD 3 / Almathera Ten on Ten - Disc 3: CDPD3.iso / scope / 051-075 / scopedisk69 / cclat / src / cc.c < prev    next >
C/C++ Source or Header  |  1995-03-19  |  24KB  |  881 lines

  1. /*
  2.  * cc -- unix-like compiler driver for amiga lattice c
  3.  *
  4.  * adapted for lattice version 5.0 and extensively modified
  5.  *   by Miles Bader, from the original by Fred Fish (copyright
  6.  *   follows).
  7.  */
  8.  
  9. /************************************************************************
  10.  *                                                                     *
  11.  *                     Copyright (c) 1985, Fred Fish                   *
  12.  *                         All Rights Reserved                         *
  13.  *                                                                     *
  14.  *     This software and/or documentation is released into the         *
  15.  *     public domain for personal, non-commercial use only.            *
  16.  *     Limited rights to use, modify, and redistribute are hereby      *
  17.  *     granted for non-commercial purposes, provided that all          *
  18.  *     copyright notices remain intact and all changes are clearly     *
  19.  *     documented.  The author makes no warranty of any kind with      *
  20.  *     respect to this product and explicitly disclaims any implied    *
  21.  *     warranties of merchantability or fitness for any particular     *
  22.  *     purpose.                                                        *
  23.  *                                                                     *
  24.  ************************************************************************
  25.  */
  26.  
  27. #include <stdio.h>
  28. #include <stdlib.h>
  29. #include <string.h>
  30.  
  31. #include <dos.h>
  32. #include <proto/dos.h>
  33. #include <ios1.h> /* magic */
  34.  
  35. #include "common.h"
  36. #include "list.h"
  37. #include "dstr.h"
  38. #include "op.h"
  39. #include "options.h"
  40.  
  41. #include "config.h"
  42.  
  43. static char *locate(char *file,struct list *list);     /* find a file */
  44. static void cleanObjects(int mustExist);       /* Remove .o for link and go mode */
  45. static int makeObjs();                 /* Reduce to list of object files */
  46. static int parseCommandLine();         /* Deal with command line */
  47. static int compile(struct op *op);     /* Translate from .c to .o */
  48. static int assemble(struct op *op);    /* Translate from .s to .o */
  49. static int link();                     /* Gather .o's into executable */
  50. static int runCmd(struct dstr *cmd);
  51.  
  52. #ifdef amiga
  53. #define CHECK_ABORT chkabort()
  54. #else
  55. #define CHECK_ABORT                            /* NULL expansion */
  56. #endif /* amiga */
  57.  
  58. DBUG_GLOBALS
  59.  
  60. /*
  61.  *     flags set by command line arguments
  62.  */
  63. static int debugLevel=DEFAULT_DEBUGLEVEL;      /* -g (debugging level) */
  64.  
  65. struct list *libDirs=NULL;
  66. struct list *incDirs=NULL;
  67. struct list *binDirs=NULL;
  68. struct list *defines=NULL;
  69. struct list *undefines=NULL;
  70. struct list *libs=NULL;
  71.  
  72. struct list *pass1PassThrus=NULL;
  73. struct list *pass2PassThrus=NULL;
  74. struct list *optPassThrus=NULL;
  75. struct list *linkPassThrus=NULL;
  76.  
  77. struct list *ops=NULL;
  78.  
  79. static char *outfile=DEFAULT_EXEC;     /* output file name from linker */
  80. static char *tempDir=TEMPDIR;          /* where to keep quad files */
  81. static char *sinkFile=SINKFILE;                /* where to put output from passes */
  82.  
  83. struct dstr *cmdLine=NULL;
  84.  
  85. static int abortmsg()
  86. {
  87.     if(options_IsSet(OPT_ECHO))
  88.        fprintf(stderr,"cc: aborting\n");
  89.     return 1; /* abort */
  90. }
  91.  
  92. static int cleanup(status)
  93. int status;
  94. {
  95.     if(cmdLine!=NULL)  dstr_Free(cmdLine);
  96.  
  97.     if(libDirs!=NULL)  list_Free(libDirs);
  98.     if(incDirs!=NULL)  list_Free(incDirs);
  99.     if(binDirs!=NULL)  list_Free(binDirs);
  100.     if(defines!=NULL)  list_Free(defines);
  101.     if(undefines!=NULL)        list_Free(undefines);
  102.     if(libs!=NULL)     list_Free(libs);
  103.  
  104.     if(pass1PassThrus!=NULL)   list_Free(pass1PassThrus);
  105.     if(pass2PassThrus!=NULL)   list_Free(pass2PassThrus);
  106.     if(optPassThrus!=NULL)     list_Free(optPassThrus);
  107.     if(linkPassThrus!=NULL)    list_Free(linkPassThrus);
  108.  
  109.     if(ops!=NULL)      list_Free(ops);
  110.  
  111.     return status;
  112. }
  113.  
  114. static void init()
  115. {
  116.     int *opt;
  117.  
  118.     options_Init();
  119.     for(opt=defaultOptions; *opt!=0; opt++)
  120.        options_Set(*opt);
  121.  
  122.     cmdLine=dstr_Create(30);           /* global command buffer */
  123.  
  124.     libDirs=list_Create((void **)libDirsInit);
  125.     incDirs=list_Create((void **)incDirsInit);
  126.     binDirs=list_Create((void **)binDirsInit);
  127.     defines=list_Create((void **)definesInit);
  128.     undefines=list_Create((void **)undefinesInit);
  129.     libs=list_Create((void **)libsInit);
  130.  
  131.     pass1PassThrus=list_Create(NULL);
  132.     pass2PassThrus=list_Create(NULL);
  133.     optPassThrus=list_Create(NULL);
  134.     linkPassThrus=list_Create(NULL);
  135.  
  136.     ops=list_Create(NULL);
  137.     list_SetFree(ops,op_Free);
  138. }
  139.  
  140. void main(argc, argv)
  141. int argc;
  142. char *argv[];
  143. {
  144.     int status;
  145.  
  146.     DBUG_ENTER("main");
  147.  
  148.     onexit(cleanup);
  149.     init();
  150.  
  151.     onbreak(abortmsg);
  152.  
  153.     if(parseCommandLine(argc,argv)==0)
  154.        fatal("no files specified");
  155.  
  156.     cleanObjects(FALSE);       /* get rid of existing object files if any */
  157.  
  158.     status=makeObjs();
  159.     if(status==0 && options_IsSet(OPT_LINK)){
  160.        status=link();
  161.        if(list_GetLen(ops)==1)
  162.            cleanObjects(TRUE);
  163.     }
  164.  
  165.     exit(status);
  166. }
  167.  
  168. /*
  169.  *     The following macro is used to allow optional whitespace between
  170.  *     an option and it's argument.  Argp is left pointing at the option
  171.  *     and argv and argc are adjusted accordingly if necessary.
  172.  *
  173.  *     Note that there is no check for missing option arguments.  In
  174.  *     particular, -o -V will blindly take -V as the output file name.
  175.  *
  176.  */
  177.  
  178. #define XARG(argc,argv,argp) {if(*++argp=='\0'){argp=(*argv++);argc--;}}
  179.  
  180. static int parseCommandLine(argc,argv)
  181. int argc;
  182. char **argv;
  183. {
  184.     register char *argp;    
  185.  
  186.     DBUG_ENTER("parseCommandLine");
  187.  
  188.     argc--;
  189.     argv++;
  190.     while(argc-- > 0){
  191.        CHECK_ABORT;
  192.  
  193.        argp=*argv++;
  194.  
  195.        if(*argp=='+')
  196.            options_SetByName(argp+1);
  197.        else if(*argp!='-')    
  198.            list_Add(ops,(void *)op_Create(argp));
  199.        else
  200.            switch(*++argp){
  201.                case 'c':
  202.                    options_Clear(OPT_LINK);    /* don't link object modules */
  203.                    break;
  204.                case 'p':                       /* pass thru args to a pass */
  205.                    switch(*++argp){
  206.                        case '1':               /* pass 1 */
  207.                            XARG(argc,argv,argp);                       
  208.                            list_Add(pass1PassThrus,argp);
  209.                            break;
  210.                        case '2':               /* pass 2 */
  211.                            XARG(argc,argv,argp);                       
  212.                            list_Add(pass2PassThrus,argp);
  213.                            break;
  214.                        case 'o':               /* optimizer */
  215.                            XARG(argc,argv,argp);                       
  216.                            list_Add(optPassThrus,argp);
  217.                            break;
  218.                        case 'l':               /* linking */
  219.                            XARG(argc,argv,argp);                       
  220.                            list_Add(linkPassThrus,argp);
  221.                            break;
  222.                        default:
  223.                            fatal("unknown pass '%c'; must be one of [12ol]",argp[-1]);
  224.                    }
  225.                    break;
  226.                case 'D':
  227.                    XARG(argc,argv,argp);
  228.                    list_Add(defines,(void *)argp);
  229.                    break;
  230.                case 'E':
  231.                    warning("-E unimplemented, converted to -P instead");
  232.                    /* fall through */
  233.                case 'P':
  234.                    options_Clear(OPT_COMPILE);
  235.                    options_Clear(OPT_ASSEMBLE);
  236.                    options_Clear(OPT_LINK);
  237.                    break;
  238.                case 'g':
  239.                    if(*++argp!='\0') /* optional debuggin level */
  240.                        debugLevel=atoi(argp);
  241.                    options_Set(OPT_DEBUG);
  242.                    break;
  243.                case 'I':
  244.                    XARG(argc,argv,argp);
  245.                    list_Add(incDirs,(void *)argp);
  246.                    break;
  247.                case 'l':
  248.                    XARG(argc,argv,argp);
  249.                    list_Add(libs,(void *)argp);
  250.                    break;
  251.                case 'L':
  252.                    XARG(argc,argv,argp);
  253.                    list_Add(libDirs,(void *)argp);
  254.                    break;
  255.                case 'B':
  256.                    XARG(argc,argv,argp);
  257.                    list_Add(binDirs,(void *)argp);
  258.                    break;
  259.                case 'O':
  260.                    options_Set(OPT_OPTIMIZE);
  261.                    break;
  262.                case 'o':
  263.                    XARG(argc,argv,argp);
  264.                    outfile=argp;
  265.                    break;
  266.                case 't':               /* warning, non-standard */
  267.                    XARG(argc,argv,argp);
  268.                    tempDir=argp;
  269.                    break;
  270.                case 'S':
  271.                    warning("-S option not yet implemented, ignored");
  272.                    options_Clear(OPT_ASSEMBLE);
  273.                    break;
  274.                case 'U':
  275.                    XARG(argc,argv,argp);
  276.                    list_Add(undefines,(void *)argp);
  277.                    break;
  278.                default:
  279.                    fatal("unknown option '%c'",*argp);
  280.                    break;
  281.            }
  282.     }
  283.  
  284.     DBUG_RETURN(int,list_GetLen(ops));
  285. }
  286.  
  287. /*
  288.  *     For each operand, do compilation or assembly as necessary, to
  289.  *     reduce to an object file in the current directory.
  290.  */
  291. static int makeObjs()
  292. {
  293.     int n;
  294.     void **els;
  295.     int numOps=list_GetLen(ops);
  296.     int status=0;
  297.  
  298.     DBUG_ENTER("makeObjs");
  299.  
  300.     for(n=numOps,els=list_GetEls(ops); n>0; n--,els++){
  301.        struct op *op=(struct op *)*els;
  302.  
  303.        CHECK_ABORT;
  304.  
  305.        if(numOps>1 && (op_IsC(op) || op_IsS(op)))
  306.            printf("%s.%s:\n",op->rootname,op->suffix);
  307.  
  308.        if(op_IsC(op))
  309.            status=compile(op);
  310.        else if(op_IsS(op))
  311.            status=assemble(op);
  312.     }
  313.  
  314.     DBUG_RETURN(int,status);
  315. }
  316.  
  317. /* handy little routine */
  318. void addfList(ds,fmt,list)
  319. struct dstr *ds;
  320. char *fmt;
  321. struct list *list;
  322. {
  323.     int n;
  324.     void **els;
  325.  
  326.     for(n=list_GetLen(list),els=list_GetEls(list); n>0; n--,els++)
  327.        dstr_Addf(ds,fmt,(char *)*els);
  328. }
  329.  
  330. /*
  331.  *     Note that commands to cc of the form "-l<name>" get interpreted
  332.  *     to mean use a library called "name.lib" from the library
  333.  *     directory.
  334.  *      -lm is specially interpreted to be the appropriate math library.
  335.  */
  336. static int link()
  337. {
  338.     int n;
  339.     void **els;
  340.  
  341.     DBUG_ENTER("link");
  342.  
  343.     dstr_Clear(cmdLine);
  344.  
  345.     dstr_Addf(cmdLine,"%s ",locate("blink",binDirs));
  346.  
  347.     if(options_IsSet(OPT_DETACH))
  348.        dstr_Append(cmdLine,locate("cback.o",libDirs));
  349.     else if(options_IsSet(OPT_RESIDENT)){
  350.        if(options_IsSet(OPT_CATCH))
  351.            dstr_Append(cmdLine,locate("catchres.o",libDirs));
  352.        else
  353.            dstr_Append(cmdLine,locate("cres.o",libDirs));
  354.     }else if(options_IsSet(OPT_CATCH))
  355.        dstr_Append(cmdLine,locate("catch.o",libDirs));
  356.     else
  357.        dstr_Append(cmdLine,locate("c.o",libDirs));
  358.  
  359.     for(n=list_GetLen(ops),els=list_GetEls(ops); n>0; n--,els++){
  360.        struct op *op=(struct op *)*els;
  361.        char *name=(op_IsO(op) ? op->rootname : op->basename);
  362.  
  363.        dstr_Addf(cmdLine,"+%s.o",name);
  364.     }
  365.  
  366.     if(options_IsSet(OPT_TINYMAIN))
  367.        dstr_Addf(cmdLine," define __main=__tinymain ");
  368.  
  369.     dstr_Addf(cmdLine," library ");
  370.     for(n=list_GetLen(libs),els=list_GetEls(libs); n>0; n--,els++){
  371.        char buffer[50];
  372.        char *lib=(char *)*els;
  373.  
  374.        if(strcmp(lib,"m")==0){
  375.            /* map -lm to appropiate library */
  376.  
  377.            strcpy(buffer,"lib:lcm");
  378.  
  379.            if(options_IsSet(OPT_FFP))
  380.                strcat(buffer,"ffp");
  381.            else if(options_IsSet(OPT_IEEE))
  382.                strcat(buffer,"ieee");
  383.            else if(options_IsSet(OPT_881))
  384.                strcat(buffer,"881");
  385.  
  386.            /*
  387.             * there are only r and s libraries for lcm.lib in the lattice
  388.             * distribution; if there is a way to get the lcmieee, lcmffp,
  389.             * & lcm881 libraries to work with reg-args & short-ints, I
  390.             * couldn't find it.
  391.             */
  392.            if(options_IsSet(OPT_SHORTINTS))
  393.                strcat(buffer,"s");
  394.            if(options_IsSet(OPT_REGARGS))
  395.                strcat(buffer,"r");
  396.  
  397.            strcat(buffer,".lib");
  398.        }else if(strcmp(lib,"lc")==0){
  399.            /* do the standard c library */
  400.  
  401.            strcpy(buffer,"lib:lc");
  402.  
  403.            if(options_IsSet(OPT_SHORTINTS))
  404.                strcat(buffer,"s");
  405.            if(options_IsSet(OPT_REGARGS))
  406.                strcat(buffer,"r");
  407.            if(options_IsSet(OPT_ABSDATA))
  408.                strcat(buffer,"nb");
  409.  
  410.            strcat(buffer,".lib");
  411.  
  412.            if(options_IsSet(OPT_REGARGS)){
  413.                /*
  414.                 * Now, do it AGAIN, but without registers, to catch any missing refs.
  415.                 * I don't think this is exactly the right thing to do, but there seem
  416.                 * to be internal functions missing from the register-fied libraries
  417.                 */
  418.  
  419.                strcat(buffer,"+lib:lc");
  420.  
  421.                if(options_IsSet(OPT_SHORTINTS))
  422.                    strcat(buffer,"s");
  423.                if(options_IsSet(OPT_ABSDATA))
  424.                    strcat(buffer,"nb");
  425.  
  426.                strcat(buffer,".lib");
  427.            }
  428.        }else{
  429.            sprintf(buffer,"%s.lib",lib);
  430.            strcpy(buffer,locate(buffer,libDirs));
  431.        }           
  432.  
  433.         if(n==1)
  434.            dstr_Append(cmdLine,buffer);
  435.        else
  436.            dstr_Addf(cmdLine,"%s+",buffer);
  437.     }
  438.  
  439.     if(outfile==NULL)
  440.        /* there better be at least one source file! */
  441.        outfile=((struct op *)list_GetEls(ops))->basename;
  442.  
  443.     dstr_Addf(cmdLine," to %s map nil:",outfile);
  444.  
  445.     addfList(cmdLine," %s",linkPassThrus);
  446.  
  447.     DBUG_RETURN(int,runCmd(cmdLine));
  448. }
  449.  
  450. /*
  451.  *     compile one operand from a C source program to an object module.
  452.  */
  453. static int compile(op)
  454. struct op *op;
  455. {
  456.     int status=0;
  457.  
  458.     DBUG_ENTER("compile");
  459.  
  460.     if(options_IsSet(OPT_ASSEMBLE)){
  461.        status=pass1(op);
  462.        if(status==0 && options_IsSet(OPT_COMPILE)){
  463.            CHECK_ABORT;
  464.            if(options_IsSet(OPT_OPTIMIZE))
  465.                status=optimize(op);
  466.            if(status==0)
  467.                status=pass2(op);
  468.        }
  469.     }
  470.  
  471.     DBUG_RETURN(int,status);
  472. }
  473.  
  474. /*
  475.  *     Note that because of brain-damage in the fact that -p to lc1 removes
  476.  *     all predefined defs, we must add them so replacing -c with -P in the
  477.  *     cc command line will result in the same set of predefined symbols.
  478.  *     This is rather ugly and leaves a hole for future problems if we
  479.  *     get out of sync with respect to what names the compiler predefines.
  480.  */
  481. static int pass1(op)
  482. register struct op *op;
  483. {
  484.     char tmpFile[MAXPATH];
  485.     int status;
  486.     int n;
  487.     void **els;
  488.  
  489.     DBUG_ENTER("pass1");
  490.  
  491.     dstr_Clear(cmdLine);
  492.  
  493.     dstr_Append(cmdLine,locate((options_IsSet(OPT_BIGLC1) ? "lc1b" : "lc1"),binDirs));
  494.  
  495.     if(options_IsSet(OPT_DEBUG)){
  496.        dstr_Addf(cmdLine," -d%d",debugLevel);
  497.        if(options_IsSet(OPT_OPTIMIZE)){
  498.            warning("-g incompatible with -O, -O turned off");
  499.            options_Clear(OPT_OPTIMIZE);
  500.        }
  501.     }
  502.  
  503.     if(options_IsSet(OPT_FFP))
  504.        dstr_Addf(cmdLine," -ff");
  505.     else if(options_IsSet(OPT_881))
  506.        dstr_Addf(cmdLine," -f8");
  507.     else if(options_IsSet(OPT_IEEE))
  508.        dstr_Addf(cmdLine," -fi");
  509.     else
  510.        dstr_Addf(cmdLine," -fl");
  511.  
  512.     if(options_IsSet(OPT_SHORTINTS))
  513.        dstr_Addf(cmdLine," -w");
  514.     if(options_IsSet(OPT_LONGALIGN))
  515.        dstr_Addf(cmdLine," -l");
  516.  
  517.     if(options_IsSet(OPT_020))
  518.        dstr_Addf(cmdLine," -m2");
  519.     else if(options_IsSet(OPT_030))
  520.        dstr_Addf(cmdLine," -m3");
  521.  
  522.     if(options_IsSet(OPT_CATCH) && !options_IsSet(OPT_ABSDATA)){
  523.        warning("+catch implies +abs-data");
  524.        options_Set(OPT_ABSDATA);
  525.     }
  526.  
  527.     dstr_Addf(cmdLine," -b%d",options_IsSet(OPT_ABSDATA) ? 0 : 1);
  528.     dstr_Addf(cmdLine," -r%d",options_IsSet(OPT_ABSCODE) ? 0 : 1);
  529.  
  530.     if(options_IsSet(OPT_REGARGS))
  531.        dstr_Addf(cmdLine,"r"); /* part of -r switch */
  532.  
  533.     {
  534.        char buf[15], *p=buf;
  535.  
  536.        if(options_IsSet(OPT_ANSI))             *p++='a';
  537.        if(options_IsSet(OPT_CPP))              *p++='+';
  538.        if(options_IsSet(OPT_TRAD))             *p++='l', *p++='o';
  539.        if(options_IsSet(OPT_REGARGS))          *p++='r';
  540.        if(options_IsSet(OPT_PURESTRINGS))      *p++='s';
  541.        
  542.        if(p>buf){
  543.            *p='\0';
  544.            dstr_Addf(cmdLine," -c%s",buf);
  545.        }
  546.     }
  547.  
  548.     if(options_IsSet(OPT_COMPILE)){
  549.        strcpy(tmpFile,tempDir);
  550.        strcat(tmpFile,op->basename);
  551.        strcat(tmpFile,".q");
  552.        dstr_Addf(cmdLine," -o%s",tmpFile);
  553.     }else{
  554.        strcpy(tmpFile,op->basename);
  555.        strcat(tmpFile,".pp");
  556.  
  557.        dstr_Addf(cmdLine," -o%s -p",tmpFile);
  558.     }
  559.  
  560.     for(n=list_GetLen(undefines),els=list_GetEls(undefines); n>0; n--,els++){
  561.        /*************************
  562.        dstr_Addf(cmdLine," -u%s",(char *)*els);
  563.        **************************/
  564.        warning("-U%s ignored! (unimplemented)",(char *)*els);
  565.     }
  566.  
  567.     addfList(cmdLine," -d%s",defines);
  568.     addfList(cmdLine," %s",pass1PassThrus);
  569.  
  570.     for(n=list_GetLen(incDirs),els=list_GetEls(incDirs); n>0; n--,els++){
  571.        char *id=(*els);
  572.        int len=strlen(id);
  573.  
  574.        dstr_Addf(cmdLine," -i%s",*els);
  575.  
  576.        if(len>0 && id[len-1]!=':' && id[len-1]!='/')
  577.            dstr_Addf(cmdLine,"/");
  578.     }
  579.  
  580.     dstr_Addf(cmdLine," %s",op->rootname);
  581.  
  582.     status=runCmd(cmdLine);
  583.     if(status==0 && options_IsSet(OPT_EXEC) && !readable(tmpFile))
  584.        status=1;
  585.  
  586.     DBUG_RETURN(int,status);
  587. }
  588.  
  589. /* run the optimizer */
  590. static int optimize(op)
  591. struct op *op;
  592. {
  593.     DBUG_ENTER("optimize");
  594.  
  595.     dstr_Clear(cmdLine);
  596.     dstr_Addf(cmdLine,"%s %s%s",locate("go",binDirs),tempDir,op->basename);
  597.  
  598.     addfList(cmdLine," %s",optPassThrus);
  599.  
  600.     DBUG_RETURN(int,runCmd(cmdLine));
  601. }
  602.  
  603. /*
  604.  *     Run second pass of compiler on a single operand.
  605.  */
  606. static int pass2(op)
  607. struct op *op;
  608. {
  609.     char objFile[MAXPATH];
  610.     int status;
  611.  
  612. #ifdef DBUG
  613.     fprintf(stderr,"Entering pass2...\n");
  614. #endif
  615.  
  616.     DBUG_ENTER("pass2");
  617.  
  618.     dstr_Clear(cmdLine);
  619.  
  620.     dstr_Append(cmdLine,locate("lc2",binDirs));
  621.  
  622.     if(!options_IsSet(OPT_STACKCHECK))
  623.        dstr_Addf(cmdLine," -v");
  624.  
  625.     strcpy(objFile,op->basename);
  626.     strcat(objFile,".o");
  627.  
  628.     dstr_Addf(cmdLine," -o%s",objFile);
  629.  
  630.     dstr_Addf(cmdLine," %s%s",tempDir,op->basename);
  631.  
  632.     addfList(cmdLine," %s",pass2PassThrus);
  633.  
  634.     status=runCmd(cmdLine);
  635.     if(status==0 && options_IsSet(OPT_EXEC) && !readable(objFile))
  636.        status=1;
  637.  
  638.     DBUG_RETURN(int,status);
  639. }
  640.  
  641. /*
  642.  *     I have not yet had occasion to use the macro assembler,so this
  643.  *     part is not yet implemented.  If anyone wants to send me the
  644.  *     appropriate code, I will be glad to install it.
  645.  */
  646. static int assemble(op)
  647. struct op *op;
  648. {
  649.     DBUG_ENTER("assemble");
  650.     warning("assembly pass not yet implemented");
  651.     DBUG_RETURN(int,1);
  652. }
  653.  
  654. static void filteredOutputFrom(source,filter)
  655. FILE *source;
  656. char **filter;
  657. {
  658.     char buf[200];
  659.  
  660.     DBUG_ENTER("FilteredOutputFrom");
  661.  
  662.     while(!feof(source)){
  663.        char **ignore;
  664.  
  665.        fgets(buf,sizeof(buf),source);
  666.  
  667.        for(ignore=filter; *ignore!=NULL; ignore++)
  668.            if(strncmp(*ignore,buf,strlen(*ignore))==0)
  669.                break;
  670.  
  671.        if(*ignore==NULL)
  672.            fputs(buf,stdout);
  673.     }
  674.  
  675.     DBUG_VOID_RETURN;
  676. }
  677.  
  678. #ifdef AMIGA
  679.  
  680. static int execToFile(cmd,sink)
  681. char *cmd;
  682. FILE *sink;
  683. {
  684.     /* this is a dopey version that uses Execute, since I can't get fork to work */
  685.     long fh;
  686.  
  687.     DBUG_ENTER("execToFile");
  688.  
  689.     if(sink==NULL)
  690.        fh=0;
  691.     else
  692.        fh=chkufb(fileno(sink))->ufbfh;
  693.  
  694.     DBUG_RETURN(int,Execute(cmd,0L,fh)!=(-1));
  695.  
  696. #if 0
  697.     char *argv[50],**argp=argv;
  698.     struct ProcID child;
  699.     static struct FORKENV env={0,0,0,0,0,NULL};
  700.     int i;
  701.  
  702.     DBUG_ENTER("execToFile");
  703.  
  704.     if(cmd==NULL)
  705.        DBUG_RETURN(int,1);
  706.  
  707.     /* this is sort of stupid, cause forkv will just put them back together,
  708.      * but oh well...
  709.      */
  710.     *argp=strtok(cmd," \t");
  711.     while(*argp!=NULL)
  712.        *++argp=strtok(NULL," \t");
  713.  
  714.     if(sink==NULL)
  715.         env.std_out=0;
  716.     else{
  717.        struct UFB *ufb=chkufb(fileno(sink));
  718.        int i;
  719.  
  720.        printf("argv[%d]:",argp-argv);
  721.        for(argp=argv;*argp!=NULL;argp++)
  722.            printf(" %s",*argp);
  723.        putchar('\n');
  724.  
  725.        printf("env: %d, %d, %d, %d, %d, %d\n",
  726.                env.priority, env.stack, env.std_in, env.std_out,
  727.                env.console, env.msgport);
  728.  
  729.        printf("ufb==0x%x, fh==0x%x, go? ",ufb,ufb->ufbfh);
  730.  
  731.        fflush(stdout);
  732.  
  733.        env.std_out=ufb->ufbfh; /* magic to get amigados handle from FILE */
  734.     }
  735.  
  736.     if((i=forkv(argv[0],argv,&env,&child))==-1){
  737.         poserr("forkv");
  738.        DBUG_RETURN(int,1);
  739.     }
  740.  
  741.     printf("Fork returns: %d\n",i);
  742.  
  743.     DBUG_RETURN(int,wait(&child));
  744. #endif
  745. }
  746.  
  747. #endif
  748.  
  749. static int runCmd(cmd)
  750. struct dstr *cmd;
  751. {
  752.     int status;
  753.     char *buf=dstr_GetBuf(cmd);
  754.     
  755.     DBUG_ENTER("RunCommand");
  756.  
  757.     DBUG_3("cmd","execute '%s'",buf);
  758.     if(options_IsSet(OPT_ECHO)){
  759.        puts(buf);
  760.        fflush(stdout);
  761.     }
  762.  
  763.     CHECK_ABORT;
  764.  
  765.     if(options_IsSet(OPT_EXEC)){
  766.        FILE *sink;
  767.  
  768.        if(sinkFile!=NULL && options_IsSet(OPT_FILTER)){
  769.            sink=fopen(sinkFile,"w+");
  770.            if(sink==NULL)
  771.                perror(sinkFile);
  772.        }else
  773.            sink=NULL;
  774.  
  775.        status=execToFile(buf,sink);
  776.        DBUG_3("sys","subcommand returns status %d",status);
  777.  
  778.        if(sink!=NULL){
  779.            rewind(sink);
  780.            filteredOutputFrom(sink,filteredPrefixes);
  781.            fclose(sink);
  782.            unlink(sinkFile);
  783.        }
  784.  
  785.        DBUG_RETURN(int,status);
  786.     }else
  787.        DBUG_RETURN(int,0);
  788. }
  789.  
  790. /*
  791.  *     Look through the list of paths pointed to by "vec" until we find
  792.  *     a file with name given pointed to by "namep".  If none is found,
  793.  *     the name pointed to by namep is returned.
  794.  */
  795. static char *locate(name,paths)
  796. char *name;
  797. struct list *paths;
  798. {
  799.     static char namebuf[MAXPATH];
  800.     void **els;
  801.     int n;
  802.     
  803.     DBUG_ENTER("locate");
  804.  
  805.     if(strchr(name,':')!=NULL || *name=='/')
  806.        return name;    /* absolute */
  807.        
  808.     for(n=list_GetLen(paths),els=list_GetEls(paths); n>0; n--,els++){
  809.        int len=strlen((char *)*els);
  810.  
  811.        strcpy(namebuf,(char *)*els);
  812.        if(len>0 && namebuf[len-1]!=':' && namebuf[len-1]!='/')
  813.            strcat(namebuf,"/");
  814.        strcat(namebuf,name);
  815.  
  816.        DBUG_3("try","look for '%s'",namebuf);
  817.        if(readable(namebuf)){
  818.            name=namebuf;
  819.            break;
  820.        }
  821.     }
  822.  
  823.     DBUG_RETURN(char *,name);
  824. }
  825.  
  826. /*
  827.  *     Check to see if the file exists and is readable.
  828.  */
  829. static int readable(name)
  830. char *name;
  831. {
  832.     register int status=0;
  833.     register long fildes;
  834.     
  835.     DBUG_ENTER("readable");
  836.  
  837. #ifdef unix
  838.     fildes=open(name,O_RDONLY);
  839.     if(fildes >= 0){
  840.        (void) close(fi d4s);
  841.        status=1;
  842.     }
  843. #else
  844.     fildes=Lock(name,ACCESS_READ);
  845.     if(fildes != 0){
  846.        UnLock(fildes);
  847.        status=1;
  848.     }
  849. #endif
  850.  
  851.     DBUG_RETURN(int,status);
  852. }
  853.  
  854. /*
  855.  *     If an executable is made from a single C file, the normal behavior
  856.  *     for the unix environment is to treat the .o file as an intermediate
  857.  *     file and remove it, so we follow suit.
  858.  */
  859. static void cleanObjects(mustExist)
  860. int mustExist;
  861. {
  862.     int n;
  863.     void **els;
  864.  
  865.     DBUG_ENTER("cleanObjects");
  866.        
  867.     for(n=list_GetLen(ops),els=list_GetEls(ops); n>0; n--,els++){
  868.        char buf[MAXPATH];
  869.         struct op *op=(struct op *)*els;
  870.  
  871.        if(!op_IsO(op)){
  872.            strcpy(buf,op->basename);
  873.            strcat(buf,".o");
  874.            if(unlink(buf)!=0 && mustExist)
  875.                warning("can't delete '%s'",buf);
  876.         }
  877.     }
  878.  
  879.     DBUG_VOID_RETURN;
  880. }
  881.